package model

import (
	"common/helper"
	myredis "common/redis"
	myUserHelp "common/userHelp"
	"database/sql"
	"errors"
	"fmt"
	g "github.com/doug-martin/goqu/v9"
	"github.com/shopspring/decimal"
	"github.com/valyala/fasthttp"
	"strconv"
	"time"
)

// tblWithdraw 出款
type tblWithdraw struct {
	ID            string  `db:"id" json:"id" cbor:"id"`                      //
	OID           string  `db:"oid" json:"oid" cbor:"oid"`                   //转账前的金额
	UID           string  `db:"uid" json:"uid" cbor:"uid"`                   //用户ID
	ParentId      string  `db:"parent_id" json:"parent_id" cbor:"parent_id"` //用户ID
	FID           string  `db:"fid" json:"fid" cbor:"fid"`                   //通道id
	Flag          string  `db:"flag" json:"flag" cbor:"flag"`                //
	ChannelName   string  `db:"channel_name" json:"channel_name" cbor:"channel_name"`
	Amount        float64 `db:"amount" json:"amount" cbor:"amount"`                //提款金额
	RealAmount    float64 `db:"real_amount" json:"real_amount" cbor:"real_amount"` //提款金额
	Balance       float64 `db:"balance" json:"balance" cbor:"balance"`             //玩家余额
	Deposit       string  `db:"deposit" json:"deposit" cbor:"deposit"`
	Withdraw      string  `db:"withdraw" json:"withdraw" cbor:"withdraw"`
	DepositTimes  string  `db:"deposit_times" json:"deposit_times" cbor:"deposit_times"`
	WithdrawTimes string  `db:"withdraw_times" json:"withdraw_times" cbor:"withdraw_times"`
	UpScore       float64 `db:"up_score" json:"up_score" cbor:"up_score"`                //金额
	Fee           float64 `db:"fee" json:"fee" cbor:"fee"`                               //手续费
	State         int     `db:"state" json:"state" cbor:"state"`                         //0:待确认:1存款成功2:已取消
	Automatic     string  `db:"automatic" json:"automatic" cbor:"automatic"`             //银行名
	PixAccount    string  `db:"pix_account" json:"pix_account" cbor:"pix_account"`       //银行名
	RealName      string  `db:"real_name" json:"real_name" cbor:"real_name"`             //持卡人姓名
	PixId         string  `db:"pix_id" json:"pix_id" cbor:"pix_id"`                      //银行卡号
	CreatedAt     int64   `db:"created_at" json:"created_at" cbor:"created_at"`          //
	ConfirmAt     int64   `db:"confirm_at" json:"confirm_at" cbor:"confirm_at"`          //确认时间
	ConfirmUID    string  `db:"confirm_uid" json:"confirm_uid" cbor:"confirm_uid"`       //确认人uid
	ReviewRemark  string  `db:"review_remark" json:"review_remark" cbor:"review_remark"` //确认人名
	WithdrawAt    int64   `db:"withdraw_at" json:"withdraw_at" cbor:"withdraw_at"`       //三方场馆ID
	Remark        string  `db:"remark" json:"remark" cbor:"remark"`                      //玩家备注
	OperatorId    string  `json:"operator_id" db:"operator_id"`
	OperatorName  string  `json:"operator_name" db:"operator_name"`
	BusinessId    string  `json:"business_id" db:"business_id"`
	BusinessName  string  `json:"business_name" db:"business_name"`
	ConfirmName   string  `json:"confirm_name" db:"confirm_name"`

	Isbloger int `json:"is_bloger" db:"is_bloger"`
}

type WithdrawSum struct {
	RealAmount    float64 `db:"real_amount" json:"real_amount"`
	Fee           float64 `db:"fee" json:"fee"`
	Amount        float64 `db:"amount" json:"amount"`
	SuccessAmount float64 `db:"success_amount" json:"success_amount"`
	SuccessNum    int     `db:"success_num" json:"success_num"`
}

// WithdrawData 取款数据
type WithdrawData struct {
	T int64         `json:"total"`
	D []tblWithdraw `json:"d"`
	S WithdrawSum   `json:"s"`
}

// 订单回调response
type paymentCallbackResp struct {
	AppId           string `json:"appId"`           //机构号
	CustId          string `json:"custId"`          //商户编号
	MerchantOrderId string `json:"merchantOrderId"` // 商户订单号
	Order           string `json:"order"`           // 平台订单号
	OrderStatus     string `json:"orderStatus"`     // 业务状态
	Amount          string `json:"amount"`          //金额
	Sign            string `json:"sign"`            // 签名
}
type RiskHistoryParam struct {
	Id           string `json:"id"`
	Uid          string `json:"uid"`
	TimeType     string `json:"time_type"`
	StartTime    string `json:"start_time"`
	EndTime      string `json:"end_time"`
	ComStartTime string `json:"com_start_time"`
	ComEndTime   string `json:"com_end_time"`
	MaxAmount    string `json:"max_amount"`
	MinAmount    string `json:"min_amount"`
	ConfirmName  string `json:"confirm_name"`
	ConfirmUid   string `json:"confirm_uid"`
	State        string `json:"state"`
	CPF          string `json:"cpf"`
	Page         int    `json:"page"`
	PageSize     int    `json:"page_size"`
	OderBY       string `json:"order_by"`
	OderType     string `json:"order_type"`
	PixId        string `json:"pix_id"`
	OperatorId   string `json:"operator_id"`
	BusinessId   string `json:"business_id"`
	IsBolger     string `json:"is_bloger"`
	IsDeposit    string `json:"is_deposit"`
	ExportExcel  int    `json:"export_excel"`
}

// WithdrawList 提款记录
func WithdrawList(param RiskHistoryParam, ctx *fasthttp.RequestCtx) (WithdrawData, error) {
	data := WithdrawData{}
	where := "b.tester=1"
	oderBy := "a.created_at"
	oderType := "desc"
	if param.Uid != "" {
		where += " and a.uid=" + param.Uid
	}
	if param.Id != "" {
		where += " and a.id=" + param.Id
	}
	if param.IsBolger != "" {
		where += " and i.is_bloger=" + param.IsBolger
	}
	if param.IsDeposit == "1" {
		where += " and e.deposit>0"
	}
	if param.IsDeposit == "2" {
		where += " and e.deposit=0"
	}
	if param.ConfirmUid != "" {
		where += " and (a.confirm_uid like '%" + param.ConfirmUid + "%' or a.confirm_name like '%" + param.ConfirmUid + "%')"
	}
	if param.ConfirmName != "" {
		where += " and (a.confirm_uid like '%" + param.ConfirmName + "%' or a.confirm_name like '%" + param.ConfirmName + "%')"
	}
	loginUser := GetLoginUser(ctx)
	if loginUser.Operator != "" {
		where += " and b.operator_id=" + loginUser.Operator
	}
	if loginUser.Businsess != "" {
		where += " and b.business_id=" + loginUser.Businsess
	}

	if param.State != "" {
		if param.State != "-1" {
			where += " and a.state=" + param.State
			if param.State == strconv.Itoa(WithdrawReviewing) {
				if param.OderBY == "" {
					oderBy = "i.is_bloger"
					oderType = "asc"
				}
			}

			if loginUser.Operator != "" || loginUser.Businsess != "" {
				//if param.State == strconv.Itoa(WithdrawReviewing) || param.State == strconv.Itoa(WithdrawHangup) {
				//	where += " and (a.state=" + strconv.Itoa(WithdrawReviewing) + " or a.state=" + strconv.Itoa(WithdrawHangup) + ")"
				//}
			} else {
				//总后台不显示 渠道
				//where += " and c.withdraw_button=0"
			}
		}
	} else {
		where += " and a.state<>" + strconv.Itoa(WithdrawReviewing) + " and a.state<>" + strconv.Itoa(WithdrawHangup)
	}

	if param.MinAmount != "" {
		where += " and a.amount>=" + param.MinAmount
	}
	if param.MaxAmount != "" {
		where += " and a.amount<=" + param.MaxAmount
	}
	timeStr := "created_at"
	if param.TimeType == "1" {
		timeStr = "confirm_at"
	}
	if param.StartTime != "" {
		StartTime, _ := helper.TimeToLoc(param.StartTime, loc)
		where += " and a." + timeStr + ">='" + strconv.FormatInt(StartTime, 10) + "'"
	}
	if param.EndTime != "" {
		EndTime, _ := helper.TimeToLoc(param.EndTime, loc)
		where += " and a." + timeStr + "<='" + strconv.FormatInt(EndTime, 10) + "'"
	}
	if param.ComStartTime != "" {
		ComStartTime, _ := helper.TimeToLoc(param.ComStartTime, loc)
		where += " and a.confirm_at>='" + strconv.FormatInt(ComStartTime, 10) + "'"
	}
	if param.ComEndTime != "" {
		ComEndTime, _ := helper.TimeToLoc(param.ComEndTime, loc)
		where += " and a.confirm_at<='" + strconv.FormatInt(ComEndTime, 10) + "'"
	}
	if param.CPF != "" {
		where += " and a.pix_id like '%" + param.CPF + "%'"
	}

	if param.OderBY != "" {
		oderBy = param.OderBY
	}
	if param.OderType != "" {
		oderType = param.OderType
	}

	table := "tbl_withdraw"
	join := " left join tbl_member_base as b on b.uid=a.uid"          //玩家表
	join += " left join tbl_operator_info as c on c.id=b.operator_id" //渠道表
	join += " left join tbl_business_info as d on d.id=b.business_id" //业务员表
	join += " left join tbl_member_accu as e on e.uid=a.uid"
	join += " left join view_member_adjust as f on f.uid=a.uid"
	join += " left join tbl_pay_factory as g on g.fid=a.fid"
	join += " left join tbl_member_controller_button as i on i.uid=a.uid"

	order := oderBy + " " + oderType

	offset := (param.Page - 1) * param.PageSize
	if param.Page >= 1 {
		count := "select count(1) from " + table + " as a " + join + " where " + where

		err := meta.MerchantDB.Get(&data.T, count)
		if err != nil {

			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), count), "数据库错误")
		}
		if (data.T) == 0 {
			return data, nil
		}
	}

	field := "a.*" +
		",ifnull(b.remake,'') remark" +
		",ifnull(e.deposit,0) deposit" +
		",ifnull(e.withdraw,0) withdraw" +
		",ifnull(e.deposit_times,0) deposit_times" +
		",ifnull(e.withdraw_times,0) withdraw_times" +
		",ifnull(f.amount,0) up_score" +
		",ifnull(g.name,0) channel_name" +
		",ifnull(c.id,'') operator_id" +
		",ifnull(c.operator_name,'') operator_name" +
		",ifnull(d.id,'') business_id" +
		",ifnull(i.is_bloger,2) is_bloger" +
		",ifnull(d.account_name,'') as business_name"

	query := "select " + field + " from " + table + "  as a " + join + " where " + where + " order by " + order + " limit " + strconv.Itoa(param.PageSize) + " offset " + strconv.Itoa(offset)

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil && err != sql.ErrNoRows {

		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if param.ExportExcel == 1 {
		return data, nil
	}
	//统计
	sfield := "ifnull(sum(a.amount),0) amount," +
		"ifnull(sum(a.fee),0) fee"
	query = "select " + sfield + " from " + table + " as a " + join + " where " + where

	err = meta.MerchantDB.Get(&data.S, query)
	//成功统计
	sfield = "ifnull(sum(a.amount),0) success_amount," +
		"count(1) success_num"
	query = "select " + sfield + " from " + table + " as a " + join + " where (a.state=374 or a.state=376) and " + where
	err = meta.MerchantDB.Get(&data.S, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	(data.S).RealAmount = (data.S).Amount - (data.S).Fee
	RealAmount := fmt.Sprintf("%.2f", (data.S).RealAmount)
	(data.S).RealAmount, _ = strconv.ParseFloat(RealAmount, 64)

	SuccessAmount := fmt.Sprintf("%.2f", (data.S).SuccessAmount)
	(data.S).SuccessAmount, _ = strconv.ParseFloat(SuccessAmount, 64)

	return data, nil
}

// 提款列表数据处理
func WithdrawListOpt(data WithdrawData, exportExcel int) (WithdrawData, [][]interface{}) {
	exportData := [][]interface{}{}
	for key, value := range data.D {
		data.D[key].RealAmount = value.Amount - value.Fee
		RealAmount := fmt.Sprintf("%.2f", data.D[key].RealAmount)
		data.D[key].RealAmount, _ = strconv.ParseFloat(RealAmount, 64)
		data.D[key].Balance = myredis.GetUserFieldFloat64(value.UID, "tbl_member_balance:brl")
		data.D[key].ConfirmUID = value.ConfirmName

		if exportExcel == 1 {
			state := ""
			switch value.State {
			case 371:
				state = "审核中"
			case 372:
				state = "审核拒绝（退币）"
			case 373:
				state = "三方处理中"
			case 374:
				state = "提款成功"
			case 375:
				state = "提交三方失败并退币"
			case 377:
				state = "三方回调失败并退币"
			case 378:
				state = "挂起"
			case 381:
				state = "审核拒绝（没收）"
			case 379:
				state = "失败（手动）"
			case 376:
				state = "成功（手动）"
			}
			single := []interface{}{
				value.ID,
				value.UID,
				value.Amount,
				value.Fee,
				data.D[key].RealAmount,
				state,
				time.Unix(value.CreatedAt, 0).Format("2006-01-02 15:04:05"),
			}
			exportData = append(exportData, single)
		}
	}
	return data, exportData
}

// 提交三方
func WithdrawToThird(id string, record g.Record) error {
	helper.InfoLog("提交三方：id---%s", id)

	db := meta.MerchantDB
	query := "select * from tbl_withdraw where id='" + id + "' for update"
	order := tblWithdraw{}
	err := db.Get(&order, query)
	if err != nil {
		return errors.New("数据库错误")
	}
	helper.InfoLog("订单初始状态：%s---%s", order.ID, order.State)
	//判断订单状态
	if order.State != WithdrawReviewing && order.State != WithdrawHangup {
		return errors.New(helper.OrderStateErr)
	}

	p, err := CachePayFactory(order.FID)
	if err != nil {
		return err
	}

	if len(p.Fid) == 0 {
		return errors.New(helper.CateNotExist)
	}

	//渠道额度判断

	monthDate := time.Now().Format("2006-01")
	monthDate = monthDate + "-01"
	SqlSelect := fmt.Sprintf("select IFNULL(sum(withdraw),0) from tbl_report_daily where business_id = 0 and operator_id=%s and created_at>='%s'", myUserHelp.GetMemberOperatorId(order.UID), monthDate)
	var totalWithdraw = 0.0
	err = db.Get(&totalWithdraw, SqlSelect)
	if err != nil {
		return errors.New(helper.ServerErr)
	}

	var withdrawLimit = 0.00
	SqlSelect = fmt.Sprintf("select auto_withdrawal_limit from tbl_operator_quota_manage where operator_id=%s", myUserHelp.GetMemberOperatorId(order.UID))
	err = db.Get(&withdrawLimit, SqlSelect)
	if err != nil {
		return errors.New(helper.ServerErr)
	}

	if totalWithdraw+order.Amount > withdrawLimit {
		return errors.New("超过渠道额度限制，审核失败")
	}
	//先改状态
	query, _, _ = dialect.Update("tbl_withdraw").Set(record).Where(g.Ex{"id": id, "state": []int{WithdrawReviewing, WithdrawHangup}}).ToSQL()
	_, err = db.Exec(query)
	if err != nil {
		return errors.New("数据库错误")
	}

	//提交三方
	order.RealAmount = order.Amount - order.Fee
	RealAmount, _ := strconv.ParseFloat(fmt.Sprintf("%f", order.RealAmount), 64)

	pixType := "CPF"
	switch order.Flag {
	case "1":
		pixType = "CPF"
	case "2":
		pixType = "PHONE"
	case "3":
		pixType = "EMAIL"
	case "4":
		pixType = "CNPJ"
	}
	data := withdrawResp{}
	if order.FID == "2" {
		data, err = withdrawEpayOrder(RealAmount, order.PixAccount, order.UID, order.PixId, pixType, order.ID, p, order.RealName)
	}
	if order.FID == "4" {
		data, err = withdrawJeepayOrder(RealAmount, order.PixAccount, order.UID, order.PixId, pixType, order.ID, p, order.RealName)
	}
	if order.FID == "6" {
		data, err = withdrawCepayOrder(RealAmount, order.PixAccount, order.UID, order.PixId, pixType, order.ID, p, order.RealName)
	}
	if order.FID == "8" {
		data, err = withdrawBetCatPayOrder(RealAmount, order.PixAccount, order.UID, order.PixId, pixType, order.ID, p, order.RealName)
	}
	if order.FID == "10" {
		data, err = withdrawU2cPayOrder(RealAmount, order.PixAccount, order.UID, order.PixId, pixType, order.ID, p, order.RealName)
	}

	if order.FID == "12" {
		data, err = withdrawPay4Order(RealAmount, order.PixAccount, order.UID, order.PixId, pixType, order.ID, p, order.RealName)
	}
	if err != nil {
		helper.InfoLog("提交三方返回错误：%s", err.Error())
	}
	helper.InfoLog("提交三方返回：%s---%s---%s---%s", order.ID, err, data.Code, data.OrdStatus)

	//更新为三方订单号
	//query, _, _ = dialect.Update("tbl_withdraw").Set(g.Record{"oid": data.Order}).Where(g.Ex{"id": order.ID}).ToSQL()
	//_, err = db.Exec(query)

	if data.OrdStatus == "08" {
		query, _, _ = dialect.Update("tbl_withdraw").Set(g.Record{"state": WithdrawFailed}).Where(g.Ex{"id": order.ID}).ToSQL()
		db.Exec(query)

		ret, _ := UpdateBalance(order.UID, order.Amount, helper.TransactionWithDrawFail, order.ID)
		if ret == false {
			return errors.New("数据库错误")
		}
		myUserHelp.AddUnlockAmount(order.UID, order.Amount)
		myUserHelp.AddAgencyAmount(order.UID, order.Amount)
		return errors.New("提交三方失败，已拒绝并退币")
	}
	return nil
}

func WithdrawToCheck(id string, record g.Record) (string, error) {
	helper.InfoLog("审查三方：id---%s", id)

	db := meta.MerchantDB
	query := "select * from tbl_withdraw where id='" + id + "'"
	order := tblWithdraw{}
	err := db.Get(&order, query)
	if err != nil {
		return "", errors.New("数据库错误")
	}
	helper.InfoLog("订单初始状态：%s---%s", order.ID, order.State)
	//判断订单状态
	if order.State != WithdrawDealing {
		return "", errors.New(helper.OrderStateErr)
	}

	p, err := CachePayFactory(order.FID)
	if err != nil {
		return "", err
	}

	if len(p.Fid) == 0 {
		return "", errors.New(helper.CateNotExist)
	}
	var data = EpayCheckBack{}
	if order.FID == "2" {
		data, err = withdrawCheckOrder(order.ID, order.OID, p)
	}
	if order.FID == "4" {
		data, err = JeepayWithdrawCheckOrder(order.ID, order.OID, p)
	}
	if order.FID == "6" {
		data, err = CepayWithdrawCheckOrder(order.ID, order.OID, p)
	}
	if order.FID == "8" {
		data, err = BetCatPayWithdrawCheckOrder(order.ID, order.OID, p)
	}
	if order.FID == "10" {
		data, err = U2cPayWithdrawCheckOrder(order.ID, order.OID, p)
	}
	if order.FID == "12" {
		data, err = Pay4WithdrawCheckOrder(order.ID, order.OID, p)
	}
	if err != nil {
		helper.InfoLog("审核三方返回错误：%s", err.Error())
		return "", err
	}
	if data.Code == "" {
		return "查询失败", nil

	}
	if data.Code == "-1" {
		// 订单不存在，已拒绝并退币
		query, _, _ = dialect.Update("tbl_withdraw").Set(g.Record{"state": WithdrawFailed}).Where(g.Ex{"id": order.ID}).ToSQL()
		db.Exec(query)

		ret, _ := UpdateBalance(order.UID, order.Amount, helper.TransactionWithDrawFail, order.ID)
		if ret == false {
			return "", errors.New("数据库错误")
		}
		myUserHelp.AddUnlockAmount(order.UID, order.Amount)
		myUserHelp.AddAgencyAmount(order.UID, order.Amount)
		return "订单不存在，已拒绝并退币", nil
	}
	return "订单处理中", nil
}

// 提款失败 操作
func WithdrawFailOpt(id string, record g.Record) error {
	if record["state"] != WithdrawReviewReject && record["state"] != WithdrawConfiscate && record["state"] != WithdrawAutoPayFailed && record["state"] != WithdrawFailManual {
		return errors.New(helper.ReviewStateErr)
	}
	//开启事务
	tx, err := meta.MerchantDB.Begin()

	if err != nil {

		return errors.New("数据库错误")
	}
	//行锁
	query := "select * from tbl_withdraw where id='" + id + "'"
	order := tblWithdraw{}
	err = meta.MerchantDB.Get(&order, query)

	if err != nil {
		tx.Rollback()
		return errors.New("数据库错误")
	}
	//判断订单状态
	if order.State != WithdrawReviewing && order.State != WithdrawHangup && order.State != WithdrawDealing {
		tx.Rollback()
		return errors.New(helper.OrderStateErr)
	}

	//24小时权限
	if order.State == WithdrawDealing && record["state"] != WithdrawAutoPayFailed {
		if (order.CreatedAt + 86400) > time.Now().Unix() {
			tx.Rollback()
			helper.InfoLog("获取并校验回调参数%s", order.ID)
			return errors.New("三方出款中状态未持续24小时")
		}
		record["state"] = WithdrawFailManual
	}
	//修改订单状态
	query, _, _ = dialect.Update("tbl_withdraw").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		tx.Rollback()
		return errors.New("数据库错误")
	}

	//退款
	if record["state"] != WithdrawConfiscate {
		ret, _ := UpdateBalance(order.UID, order.Amount, helper.TransactionWithDrawFail, order.ID)
		if ret == false {
			tx.Rollback()
			return errors.New("数据库错误")
		}
		myUserHelp.AddUnlockAmount(order.UID, order.Amount)
		myUserHelp.AddAgencyAmount(order.UID, order.Amount)
	}
	err = tx.Commit()
	if err != nil {
		return errors.New("数据库错误")
	}

	return nil
}

// 提款成功 操作
func WithdrawSuccessOpt(id string, record g.Record) error {
	if record["state"] != WithdrawSuccess && record["state"] != WithdrawSuccessManual {
		return errors.New(helper.ReviewStateErr)
	}
	//开启事务
	tx, err := meta.MerchantDB.Begin()

	if err != nil {
		return errors.New("数据库错误")
	}
	//行锁
	query := "select * from tbl_withdraw where id='" + id + "'"
	order := tblWithdraw{}
	err = meta.MerchantDB.Get(&order, query)
	if err != nil {
		tx.Rollback()
		return errors.New("数据库错误")
	}

	//判断订单状态
	if order.State != WithdrawDealing {
		tx.Rollback()
		return errors.New(helper.OrderStateErr)
	}
	//24小时权限
	if record["state"] == WithdrawSuccessManual {
		if (order.CreatedAt + 3600) > time.Now().Unix() {
			tx.Rollback()
			return errors.New("三方处理中状态未持续1小时")
		}
	}
	//修改订单状态
	query, _, _ = dialect.Update("tbl_withdraw").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		tx.Rollback()
		return errors.New("数据库错误")
	}

	//统计数据
	money := decimal.NewFromFloat(order.Amount)
	fWithdrawAmount, _ := money.Float64()
	_, errExec := meta.MerchantDB.Exec("CALL tbl_report_user_business_withdraw_update(?,?,?)", order.UID, fWithdrawAmount, time.Now().Unix())
	if errExec != nil {
		helper.GetloggerInstance().Emergencyf("CALL tbl_report_user_business_withdraw_update(%s,%0.2f,%d);	reason:%s", order.UID, fWithdrawAmount,
			time.Now().Unix(), errExec.Error())
	}

	//myUserHelp.AddUserDailyAction(order.UID, myUserHelp.Action_Withdraw)

	err = tx.Commit()
	if err != nil {
		return errors.New("数据库错误")
	}
	myUserHelp.AddTotalWithdraw(order.UID, fWithdrawAmount)
	myUserHelp.AddTotalWithdrawTimes(order.UID, 1)

	return nil
}

// 挂起/取消挂起
func WithdrawSuspend(id string, record g.Record) error {
	db := meta.MerchantDB
	query := "select * from tbl_withdraw where id='" + id + "'"
	order := tblWithdraw{}
	err := db.Get(&order, query)
	if err != nil {
		fmt.Println(err.Error())
		return errors.New("数据库错误")
	}

	//判断订单状态
	if order.State != WithdrawReviewing && order.State != WithdrawHangup {
		fmt.Println(helper.OrderStateErr)
		return errors.New(helper.OrderStateErr)
	}

	if order.State == WithdrawReviewing {
		record["state"] = WithdrawHangup
	}
	if order.State == WithdrawHangup {
		record["state"] = WithdrawReviewing
	}
	//先改状态
	query, _, _ = dialect.Update("tbl_withdraw").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err = db.Exec(query)
	if err != nil {
		fmt.Println(err.Error())
		return errors.New("数据库错误")
	}
	return nil
}

// 自动出款
//func WithdrawAutoOld() {
//	db := meta.MerchantDB
//	orderIds := []string{}
//	query := "select id from tbl_withdraw where automatic=1 and state=" + strconv.Itoa(WithdrawReviewing) + " order by created_at asc limit 2"
//	err := db.Select(&orderIds, query)
//	helper.InfoLog("自动出款%s---ids---%s", query, strings.Join(orderIds, ","))
//	if err != nil {
//		helper.InfoLog("自动出款err---%s", err)
//		return
//	}
//	if len(orderIds) == 0 {
//		return
//	}
//	//record := g.Record{
//	//	"confirm_at":  time.Now().Unix(),
//	//	"withdraw_at": time.Now().Unix(),
//	//	"confirm_uid": 0,
//	//	"automatic":   2,
//	//	"state":       WithdrawDealing,
//	//}
//	for _, id := range orderIds {
//		//err = WithdrawLock(id)
//		//if err != nil {
//		//	helper.InfoLog("自动出款,获取锁失败：订单id--%s", id)
//		//	continue
//		//}
//		helper.InfoLog("自动出款：订单id--%s", id)
//		record := g.Record{
//			"confirm_at":  time.Now().Unix(),
//			"withdraw_at": time.Now().Unix(),
//			"confirm_uid": 0,
//			"automatic":   2,
//			"state":       WithdrawDealing,
//		}
//		err = WithdrawToThird(id, record)
//		////解锁
//		//WithdrawUnLock(id)
//		if err != nil {
//			helper.InfoLog("提自动出款提交三方错误：订单id--%s--%s", id, err.Error())
//		}
//		helper.InfoLog("自动出款提交三方：订单id--%s--%s", id, err)
//	}
//}

// 自动出款
func WithdrawAuto() {
	db := meta.MerchantDB
	orderIds := ""
	query := "select id from tbl_withdraw where automatic=1 and state=" + strconv.Itoa(WithdrawReviewing) + " order by created_at asc limit 1"
	err := db.Get(&orderIds, query)
	helper.InfoLog("自动出款%s---ids---%s", query, orderIds)
	if err != nil {
		helper.InfoLog("自动出款err---%s", err)
		return
	}
	if orderIds == "" {
		return
	}
	id := orderIds

	helper.InfoLog("自动出款：订单id--%s", id)
	record := g.Record{
		"confirm_at":  time.Now().Unix(),
		"withdraw_at": time.Now().Unix(),
		"confirm_uid": 0,
		"automatic":   2,
		"state":       WithdrawDealing,
	}
	err = WithdrawToThird(id, record)

	if err != nil {
		helper.InfoLog("提自动出款提交三方错误：订单id--%s--%s", id, err.Error())
	}
	helper.InfoLog("自动出款提交三方：订单id--%s--%s", id, err)

}

// WithdrawalCallBack 提款回调
func WithdrawalCallBack(fctx *fasthttp.RequestCtx) {
	var (
		err  error
		data paymentCallbackResp
	)
	payment := &thirdEpay{}
	// 获取并校验回调参数
	data, err = payment.WithdrawCallBack(fctx)
	if err != nil {
		fctx.SetBody([]byte(`failed`))
		pushLog(err, helper.WithdrawFailure)
		return
	}
	err = WithdrawLock(data.MerchantOrderId)
	if err != nil {
		helper.InfoLog("出款回调,获取锁失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		fctx.SetBody([]byte(`success`))
		return
	}
	if data.OrderStatus == "07" {
		helper.InfoLog("出款回调,成功：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawSuccessOpt(data.MerchantOrderId, g.Record{"state": WithdrawSuccess, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	if data.OrderStatus == "08" {
		helper.InfoLog("出款回调,失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawFailOpt(data.MerchantOrderId, g.Record{"state": WithdrawAutoPayFailed, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	//解锁
	WithdrawUnLock(data.MerchantOrderId)
	fctx.SetBody([]byte(`success`))
}

func WithdrawalJeepayCallBack(fctx *fasthttp.RequestCtx) {
	var (
		err  error
		data paymentCallbackResp
	)
	payment := &thirdJeepay{}
	// 获取并校验回调参数
	data, err = payment.WithdrawJeepayCallBack(fctx)
	if err != nil {
		fctx.SetBody([]byte(`failed`))
		pushLog(err, helper.WithdrawFailure)
		return
	}
	err = WithdrawLock(data.MerchantOrderId)
	if err != nil {
		helper.InfoLog("出款回调,获取锁失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		fctx.SetBody([]byte(`success`))
		return
	}
	if data.OrderStatus == "07" {
		helper.InfoLog("出款回调,成功：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawSuccessOpt(data.MerchantOrderId, g.Record{"state": WithdrawSuccess, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	if data.OrderStatus == "08" {
		helper.InfoLog("出款回调,失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawFailOpt(data.MerchantOrderId, g.Record{"state": WithdrawAutoPayFailed, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	//解锁
	WithdrawUnLock(data.MerchantOrderId)
	fctx.SetBody([]byte(`success`))
}

func WithdrawalCepayCallBack(fctx *fasthttp.RequestCtx) {
	var (
		err  error
		data paymentCallbackResp
	)
	payment := &thirdCepay{}
	// 获取并校验回调参数
	data, err = payment.WithdrawCepayCallBack(fctx)
	if err != nil {
		fctx.SetBody([]byte(`failed`))
		pushLog(err, helper.WithdrawFailure)
		return
	}
	err = WithdrawLock(data.MerchantOrderId)
	if err != nil {
		helper.InfoLog("出款回调,获取锁失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		fctx.SetBody([]byte(`success`))
		return
	}
	if data.OrderStatus == "07" {
		helper.InfoLog("出款回调,成功：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawSuccessOpt(data.MerchantOrderId, g.Record{"state": WithdrawSuccess, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	if data.OrderStatus == "08" {
		helper.InfoLog("出款回调,失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawFailOpt(data.MerchantOrderId, g.Record{"state": WithdrawAutoPayFailed, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	//解锁
	WithdrawUnLock(data.MerchantOrderId)
	fctx.SetBody([]byte(`OK`))
}

func WithdrawBetCatPayCallBack(fctx *fasthttp.RequestCtx) {
	var (
		err  error
		data paymentCallbackResp
	)
	payment := &BetCatPay{}
	// 获取并校验回调参数
	data, err = payment.WithdrawBetCatPayCallBack(fctx)
	if err != nil {
		fctx.SetBody([]byte(`failed`))
		pushLog(err, helper.WithdrawFailure)
		return
	}
	err = WithdrawLock(data.MerchantOrderId)
	if err != nil {
		helper.InfoLog("出款回调,获取锁失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		fctx.SetBody([]byte(`success`))
		return
	}
	if data.OrderStatus == "07" {
		helper.InfoLog("出款回调,成功：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawSuccessOpt(data.MerchantOrderId, g.Record{"state": WithdrawSuccess, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	if data.OrderStatus == "08" {
		helper.InfoLog("出款回调,失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawFailOpt(data.MerchantOrderId, g.Record{"state": WithdrawAutoPayFailed, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	//解锁
	WithdrawUnLock(data.MerchantOrderId)
	fctx.SetBody([]byte(`OK`))
}

func WithdrawU2cPayCallBack(fctx *fasthttp.RequestCtx) {
	var (
		err  error
		data paymentCallbackResp
	)
	payment := &U2cPay{}
	// 获取并校验回调参数
	data, err = payment.WithdrawU2cPayCallBack(fctx)
	if err != nil {
		fctx.SetBody([]byte(`failed`))
		pushLog(err, helper.WithdrawFailure)
		return
	}
	err = WithdrawLock(data.MerchantOrderId)
	if err != nil {
		helper.InfoLog("出款回调,获取锁失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		fctx.SetBody([]byte(`success`))
		return
	}
	if data.OrderStatus == "07" {
		helper.InfoLog("出款回调,成功：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawSuccessOpt(data.MerchantOrderId, g.Record{"state": WithdrawSuccess, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	if data.OrderStatus == "08" {
		helper.InfoLog("出款回调,失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawFailOpt(data.MerchantOrderId, g.Record{"state": WithdrawAutoPayFailed, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	//解锁
	WithdrawUnLock(data.MerchantOrderId)
	fctx.SetBody([]byte(`success`))
}

func WithdrawPay4CallBack(fctx *fasthttp.RequestCtx) {
	var (
		err  error
		data paymentCallbackResp
	)
	payment := &U2cPay{}
	// 获取并校验回调参数
	data, err = payment.WithdrawU2cPayCallBack(fctx)
	if err != nil {
		fctx.SetBody([]byte(`failed`))
		pushLog(err, helper.WithdrawFailure)
		return
	}
	err = WithdrawLock(data.MerchantOrderId)
	if err != nil {
		helper.InfoLog("出款回调,获取锁失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		fctx.SetBody([]byte(`success`))
		return
	}
	if data.OrderStatus == "07" {
		helper.InfoLog("出款回调,成功：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawSuccessOpt(data.MerchantOrderId, g.Record{"state": WithdrawSuccess, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	if data.OrderStatus == "08" {
		helper.InfoLog("出款回调,失败：订单id--%s--%s", data.MerchantOrderId, data.OrderStatus)
		err := WithdrawFailOpt(data.MerchantOrderId, g.Record{"state": WithdrawAutoPayFailed, "withdraw_at": time.Now().Unix()})
		helper.InfoLog("出款回调,成功：订单id--%s--%s--%s", data.MerchantOrderId, data.OrderStatus, err)
	}
	//解锁
	WithdrawUnLock(data.MerchantOrderId)
	fctx.SetBody([]byte(`success`))
}

// WithdrawLock 锁定提款订单
// 订单因为外部因素(接口)导致的状态流转应该加锁
func WithdrawLock(id string) error {

	key := fmt.Sprintf(withdrawOrderLockKey, id)
	err := Lock(key)
	if err != nil {
		return err
	}

	return nil
}

// WithdrawUnLock 解锁提款订单
func WithdrawUnLock(id string) {
	Unlock(fmt.Sprintf(withdrawOrderLockKey, id))
}

func Lock(id string) error {

	val := fmt.Sprintf("%s%s", defaultRedisKeyPrefix, id)
	ok, err := meta.MerchantRedis.SetNX(ctx, val, "1", LockTimeout).Result()
	if err != nil {
		return pushLog(err, helper.RedisErr)
	}
	if !ok {
		return errors.New(helper.RequestBusy)
	}

	return nil
}

func Unlock(id string) {

	val := fmt.Sprintf("%s%s", defaultRedisKeyPrefix, id)
	res, err := meta.MerchantRedis.Del(ctx, val).Result()
	if err != nil || res != 1 {

	}
}
